package logica_de_presentacion;

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Frame;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.beans.PropertyVetoException;
import java.util.HashSet;

import javax.swing.JButton;
import javax.swing.JInternalFrame;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.event.InternalFrameEvent;
import javax.swing.event.InternalFrameListener;
import javax.swing.table.AbstractTableModel;

import comun.Pelicula;
import comun.PeliculaVistaNoSi;
import comun.Usuario;
import comun.ValorId_p;
import comun.ValoracionPelicula;
import logica_de_negocio.FaltanDatosEnLaBaseDeDatos;
import logica_de_negocio.excepAnadirDupli;
import logica_de_negocio.gestorPeli;
import logica_de_negocio.gestorPeliculaVistaNoSi;
import logica_de_negocio.gestorValoracionPelicula;

public class TablaPeliculasSegunUsuario extends JInternalFrame implements
		ActionListener, InternalFrameListener {

	private static final long serialVersionUID = 1L;
	private JTable tablaDatos;
	private JButton jbDetalles, jbMarcarVis, jbValorar, jbSalir;
	private JScrollPane scrollPane;
	private JPanel jpBotones;
	private HashSet<Pelicula> lp;
	private MenuInicial clasePadre;

	private Usuario usu;
	private FormularioAnadirModificarValoracion formularioAnadirModificarValoracion;
	private ValoracionPelicula vp;

	private boolean bolFilTitulo = false;
	private String filTitulo = null;
	private JButton jbFilTil;

	private boolean bolFilDir = false;
	private String filDir = null;
	private JButton jbFilDir;

	private boolean bolFilPais = false;
	private String filPais = null;
	private JButton jbFilPais;

	public TablaPeliculasSegunUsuario(MenuInicial clasePadre, Usuario usuActual) {// ANADIR
		// PARAMETROS
		// DE
		// BUSQUEDA
		// Filtrar

		super("Listar peliculas que no ha VISTO", true, false, false, false);
		this.setVisible(true);
		this.setSize(900, 700);
		this.clasePadre = clasePadre;
		this.usu = usuActual;
		this.subCompo();

	}

	public void subCompo() {

		this.getContentPane().setLayout(new BorderLayout());
		// TABLA

		// CREAMOS UN SCROLLPANE Y LE ANADIMOS LA TABLA
		scrollPane = new JScrollPane(tablaDatos);

		// ANADIMOS EL SCROLLPANE AL PANEL
		this.add(scrollPane, "Center");

		jpBotones = new JPanel(new FlowLayout());

		jbDetalles = new JButton("Ver detalles");
		jbDetalles.addActionListener(this);
		jbDetalles.setMnemonic(KeyEvent.VK_V);
		jbDetalles
				.setToolTipText("Muestra mas detalles de la pelicula selecionada");
		jpBotones.add(jbDetalles);

		jbMarcarVis = new JButton("Marcar Vista");
		jbMarcarVis.addActionListener(this);
		jbMarcarVis.setMnemonic(KeyEvent.VK_M);
		jbMarcarVis.setToolTipText("Marcar como vista la pelicula selecionada");
		jpBotones.add(jbMarcarVis);

		jbValorar = new JButton("Comentar/Valorar");
		jbValorar.addActionListener(this);
		jbValorar.setMnemonic(KeyEvent.VK_C);
		jbValorar
				.setToolTipText("Comentar o/y valorar la pelicula de la base de datos");
		jpBotones.add(jbValorar);

		jbFilTil = new JButton("Filtro Titulo");
		jbFilTil.addActionListener(this);
		jbFilTil.setToolTipText("Anadir filtro por Titulo");
		jpBotones.add(jbFilTil);

		jbFilDir = new JButton("Filtro Director");
		jbFilDir.addActionListener(this);
		jbFilDir.setToolTipText("Anadir filtro por Director");
		jpBotones.add(jbFilDir);

		jbFilPais = new JButton("Filtro Pais");
		jbFilPais.addActionListener(this);
		jbFilPais.setToolTipText("Anadir filtro por Pais");
		jpBotones.add(jbFilPais);

		jbSalir = new JButton("Salir");
		jbSalir.addActionListener(this);
		jbSalir.setMnemonic(KeyEvent.VK_S);
		jbSalir.setToolTipText("Salir  de la tabla");
		jpBotones.add(jbSalir);

		this.getContentPane().add(jpBotones, "South");

	}
	@Override
	public void actionPerformed(ActionEvent e) {

		JButton botonPulsado = (JButton) e.getSource();

		if (botonPulsado == jbDetalles) {
			try {
				String titulo = (String) tablaDatos.getValueAt(
						tablaDatos.getSelectedRow(), 0);
				String director = (String) tablaDatos.getValueAt(
						tablaDatos.getSelectedRow(), 1);
				gestorPeli gp = new gestorPeli();
				Pelicula des = gp.getPelicula(gp.getId(titulo, director));
				JOptionPane.showMessageDialog(new Frame(), des.toString());
				this.refreshTable();
			} catch (IndexOutOfBoundsException sinEle) {
				JOptionPane.showMessageDialog(new Frame(),
						"No hay niguna fila selecionada");
			} catch (NullPointerException sinEle2) {
				JOptionPane.showMessageDialog(new Frame(),
						"No hay niguna fila selecionada");
			} catch (FaltanDatosEnLaBaseDeDatos e1) {
				JOptionPane.showMessageDialog(new Frame(), e1.toString());
			} catch (ClassNotFoundException e1) {
				JOptionPane
						.showMessageDialog(null,
								"No existe la base de datos comprueba que existe el archivo sqlite");
				this.dispose();
			}
		}
		if (botonPulsado == jbMarcarVis) {

			try {
				String titulo = (String) tablaDatos.getValueAt(
						tablaDatos.getSelectedRow(), 0);
				String director = (String) tablaDatos.getValueAt(
						tablaDatos.getSelectedRow(), 1);
				gestorPeli gp = new gestorPeli();
				Pelicula p = gp.getPelicula(gp.getId(titulo, director));

				marcarComoVista(p);

			} catch (IndexOutOfBoundsException sinEle) {
				JOptionPane.showMessageDialog(new Frame(),
						"No hay niguna fila selecionada");
			} catch (NullPointerException sinEle2) {
				JOptionPane.showMessageDialog(new Frame(),
						"No hay niguna fila selecionada");
			} catch (FaltanDatosEnLaBaseDeDatos e1) {
				JOptionPane.showMessageDialog(new Frame(), e1.getFalta());
			} catch (ClassNotFoundException e1) {
				JOptionPane
						.showMessageDialog(null,
								"No existe la base de datos comprueba que existe el archivo sqlite");
				this.dispose();
			}
		}
		if (botonPulsado == jbValorar) {
			try {
				String titulo = (String) tablaDatos.getValueAt(
						tablaDatos.getSelectedRow(), 0);
				String director = (String) tablaDatos.getValueAt(
						tablaDatos.getSelectedRow(), 1);
				gestorPeli gp = new gestorPeli();
				Pelicula p = gp.getPelicula(gp.getId(titulo, director));

				gestorValoracionPelicula gvp = new gestorValoracionPelicula();
				vp = gvp.getValoracionPelicula(usu.getId_u(), p.getId_p());
				if (vp == null) {// No existe
					vp = new ValoracionPelicula();
					vp.setId_p(p.getId_p());
					vp.setId_u(usu.getId_u());
				}
				comertarValorar();

			} catch (IndexOutOfBoundsException sinEle) {
				JOptionPane.showMessageDialog(new Frame(),
						"No hay niguna fila selecionada");
			} catch (NullPointerException sinEle2) {
				JOptionPane.showMessageDialog(new Frame(),
						"No hay niguna fila selecionada");
			} catch (PropertyVetoException e1) {
			} catch (FaltanDatosEnLaBaseDeDatos e1) {
				JOptionPane.showMessageDialog(new Frame(), e1.getFalta());
			} catch (ClassNotFoundException e1) {
				JOptionPane
						.showMessageDialog(null,
								"No existe la base de datos comprueba que existe el archivo sqlite");
				this.dispose();
			}
		}

		if (botonPulsado == jbFilTil) {

			if (bolFilTitulo) {
				int res = JOptionPane.showConfirmDialog(new Frame(),
						"Desea retirar el filtro");
				if (res == 0) {
					bolFilTitulo = false;
					try {
						this.refreshTable();
					} catch (ClassNotFoundException e1) {
						JOptionPane
						.showMessageDialog(null,
								"No existe la base de datos comprueba que existe el archivo sqlite");
						this.dispose();
					}
				}
			} else {
				String res = JOptionPane.showInputDialog(new Frame(),
						"Indique el titulo");
				if (res != null) {
					filTitulo = res;
					bolFilTitulo = true;
				}
				try {
					this.refreshTable();
				} catch (ClassNotFoundException e1) {
					JOptionPane
					.showMessageDialog(null,
							"No existe la base de datos comprueba que existe el archivo sqlite");
					this.dispose();
				}
			}
		}

		if (botonPulsado == jbFilDir) {

			if (bolFilDir) {
				int res = JOptionPane.showConfirmDialog(new Frame(),
						"Desea retirar el filtro");
				if (res == 0) {
					bolFilDir = false;
					try {
						this.refreshTable();
					} catch (ClassNotFoundException e1) {
						JOptionPane
						.showMessageDialog(null,
								"No existe la base de datos comprueba que existe el archivo sqlite");
						this.dispose();
					}
				}
			} else {
				String res = JOptionPane.showInputDialog(new Frame(),
						"Indique el Director");
				if (res != null) {
					filDir = res;
					bolFilDir = true;
				}
				try {
					this.refreshTable();
				} catch (ClassNotFoundException e1) {
					JOptionPane
					.showMessageDialog(null,
							"No existe la base de datos comprueba que existe el archivo sqlite");
					this.dispose();
				}
			}
		}

		if (botonPulsado == jbFilPais) {

			if (bolFilPais) {
				int res = JOptionPane.showConfirmDialog(new Frame(),
						"Desea retirar el filtro");
				if (res == 0) {
					bolFilPais = false;
					try {
						this.refreshTable();
					} catch (ClassNotFoundException e1) {
						JOptionPane
						.showMessageDialog(null,
								"No existe la base de datos comprueba que existe el archivo sqlite");
						this.dispose();
					}
				}
			} else {
				String res = JOptionPane.showInputDialog(new Frame(),
						"Indique el Pais");
				if (res != null) {
					filPais = res;
					bolFilPais = true;
				}
				try {
					this.refreshTable();
				} catch (ClassNotFoundException e1) {
					JOptionPane
					.showMessageDialog(null,
							"No existe la base de datos comprueba que existe el archivo sqlite");
					this.dispose();
				}
			}
		}

		if (botonPulsado == jbSalir) {
			this.dispose();
		}
	}

	private void comertarValorar() throws PropertyVetoException {

		formularioAnadirModificarValoracion = new FormularioAnadirModificarValoracion(
				vp.getPuntuacion(), vp.getComentario());
		formularioAnadirModificarValoracion.addInternalFrameListener(this);
		clasePadre.add(formularioAnadirModificarValoracion);
		formularioAnadirModificarValoracion.setSelected(true);
	}

	private void marcarComoVista(Pelicula p) throws FaltanDatosEnLaBaseDeDatos, ClassNotFoundException {

		gestorPeliculaVistaNoSi gpvns = new gestorPeliculaVistaNoSi();
		PeliculaVistaNoSi pvns = new PeliculaVistaNoSi();
		pvns.setId_p(p.getId_p());
		pvns.setId_u(usu.getId_u());
		pvns.setVista(true);

		try {
			gpvns.addPeliculaVistaNoSi(pvns);
			if (gpvns.contenien(pvns)) {
				JOptionPane.showMessageDialog(new Frame(),
						"Pelicula marcada como vista");
				this.refreshTable();
			}
		} catch (excepAnadirDupli e) {
			pvns = null;
			pvns = gpvns.getPeliculaVistaNoSi(p.getId_p(), usu.getId_u());
			if (pvns.isVista()) {
				int res = JOptionPane
						.showConfirmDialog(new Frame(),
								"La pelicula ya esta marcada como vista, Desea desmarcarla?");
				// YES=0, NO=1,Cancel =2
				if (res == 0) {
					pvns.setVista(false);
					if (gpvns.modificarPeliculaVistaNoSi(pvns)) {
						JOptionPane.showMessageDialog(new Frame(),
								"Pelicula desmarcada");
					}
					this.refreshTable();
				}
			} else {
				pvns.setVista(true);
				if (gpvns.modificarPeliculaVistaNoSi(pvns)) {
					JOptionPane.showMessageDialog(new Frame(),
							"Pelicula marcada como vista");
					this.refreshTable();
				}
			}
		}
	}

	public void cargarPeliculas() throws ClassNotFoundException {// DAMOS LAS PELICULAS GUARDADAS
		gestorPeli gp = new gestorPeli();
		gestorPeliculaVistaNoSi gpvns = new gestorPeliculaVistaNoSi();
		HashSet<ValorId_p> PelisUsu = gpvns
				.getPeliculasVistaNoSi(usu.getId_u());
		lp = gp.getPelis(PelisUsu);
		crearTabla();
		this.setVisible(true);
		this.subCompo();
	}

	public void crearTabla() throws ClassNotFoundException {

		tablaDatos = null;// VACIAMOS SI EXISTE ALUGUNA
		myTable tmp = new myTable();
		tablaDatos = new JTable(tmp);
		tablaDatos.setPreferredScrollableViewportSize(new Dimension(200, 200));
		tablaDatos.setEnabled(true);
		// QUE PODAMOS SELECIONAR LAS FILAS
		tablaDatos.setRowSelectionAllowed(true);
		// QUE SE ACTUALICE (La tabla que contiene)
		tmp.fireTableDataChanged();
		// SI QUEREMOS QUE LA TABLA LLENE POR COMPLETO LA VENTANA EN LA ALTURA
		tablaDatos.setFillsViewportHeight(true);
		// CREAR UNA ORDENACION AUTOMATICA
		tablaDatos.setAutoCreateRowSorter(true);

	}

	private void refreshTable() throws ClassNotFoundException {
		gestorPeli gp = new gestorPeli();
		gestorPeliculaVistaNoSi gpvns = new gestorPeliculaVistaNoSi();
		HashSet<ValorId_p> PelisUsu = gpvns
				.getPeliculasVistaNoSi(usu.getId_u());
		lp = gp.getPelis(PelisUsu);
		myTable tpm = (myTable) tablaDatos.getModel();
		tpm.setData();
		tpm.fireTableDataChanged();
	}

	class myTable extends AbstractTableModel {

		/**
		 * 
		 */
		private static final long serialVersionUID = 1L;
		private String[] columName;
		private Object[][] data;

		public myTable() throws ClassNotFoundException {

			super();
			setData();
			if (usu.isEsAdmin()) {
				String[] col = { "Titulo", "Director", "Pais", "Duracion",
						"Actor principal", "N Oscar", "Fecha de estreno" };
				columName = new String[7];
				columName = col;
			} else {
				String[] col = { "Titulo", "Director", "Pais", "Duracion",
						"Actor principal", "N Oscar", "Fecha de estreno",
						"Visto" };
				columName = new String[8];
				columName = col;
			}
		}
		@Override
		public int getColumnCount() {
			return columName.length;
		}
		@Override
		public int getRowCount() {
			return data.length;
		}
		@Override
		public String getColumnName(int col) {
			return columName[col];
		}
		@Override
		public Object getValueAt(int row, int col) {

			return data[row][col];
		}

		public void setData() throws ClassNotFoundException {

			int filas = lp.size();
			int cont = 0;
			Object[][] data2 = new Object[filas][];

			// RELLENO DATOS si eres administrados
			for (Pelicula p : lp) {
				boolean add = false;

				if (bolFilTitulo) {
					if (p.getTitulo().equals(filTitulo)) {
						add = true;
					} else {
						add = false;
					}
				} else {
					add = true;
				}

				if (seguir(add)) {
					if (bolFilPais) {
						if (p.getPais().equals(filPais)) {
							add = true;
						} else {
							add = false;
						}
					} else {
						add = true;
					}
				}

				if (seguir(add)) {
					if (bolFilDir) {
						if (p.getDirector().equals(filDir)) {
							add = true;
						} else {
							add = false;
						}
					} else {
						add = true;
					}
				}
				if (seguir(add)) {
					if (usu.isEsAdmin()) {
						Object[] a = { p.getTitulo(), p.getDirector(),
								p.getPais(), p.getDuracion(),
								p.getActorPrincipal(), p.getOscar(),
								p.getFechaEstreno() };
						data2[cont] = a;
						cont++;
					} else {
						Object[] a = { p.getTitulo(), p.getDirector(),
								p.getPais(), p.getDuracion(),
								p.getActorPrincipal(), p.getOscar(),
								p.getFechaEstreno(), pelVista(p) };
						data2[cont] = a;
						cont++;
					}
				}

			}

			if (cont == 0) {
				JOptionPane
						.showMessageDialog(new Frame(),
								"No hay peliculas que cumplan las condiciones\nSe retiraran los filtros");
				bolFilTitulo = false;
				bolFilPais = false;
				bolFilDir = false;

				data = new Object[filas][];
				data = todas();

			} else {
				data = new Object[cont][];
				for (int i = 0; i < cont; i++) {// PORQUE data2 mayor que data
					data[i] = data2[i];
				}
			}
		}

		private Object[][] todas() throws ClassNotFoundException {

			Object[][] data = new Object[lp.size()][];
			int cont = 0;
			for (Pelicula p : lp) {
				if (usu.isEsAdmin()) {
					Object[] a = { p.getTitulo(), p.getDirector(), p.getPais(),
							p.getDuracion(), p.getActorPrincipal(),
							p.getOscar(), p.getFechaEstreno() };
					data[cont] = a;
					cont++;
				} else {
					Object[] a = { p.getTitulo(), p.getDirector(), p.getPais(),
							p.getDuracion(), p.getActorPrincipal(),
							p.getOscar(), p.getFechaEstreno(), pelVista(p) };
					data[cont] = a;
					cont++;
				}
			}
			return data;
		}

		private boolean seguir(boolean add) {

			boolean dev = false;

			if (add == true) {
				dev = true;
			}

			return dev;

		}

		private Boolean pelVista(Pelicula p) throws ClassNotFoundException {
			boolean dev = false;
			gestorPeliculaVistaNoSi gpvns = new gestorPeliculaVistaNoSi();
			PeliculaVistaNoSi pvns = gpvns.getPeliculaVistaNoSi(p.getId_p(),
					usu.getId_u());
			if (pvns == null) {
				// NO ESTA EN LA BASE DE DATOS
				dev = false;
			} else {
				dev = pvns.isVista();
			}
			return dev;
		}
	}
	@Override
	public void internalFrameOpened(InternalFrameEvent e) {
	}
	@Override
	public void internalFrameClosing(InternalFrameEvent e) {
	}
	@Override
	public void internalFrameClosed(InternalFrameEvent e) {

		if (e.getSource() == formularioAnadirModificarValoracion) {
			// RESTO DE DATOS
			vp.setComentario(formularioAnadirModificarValoracion.getComen());
			vp.setPuntuacion(formularioAnadirModificarValoracion.getVal());
			gestorValoracionPelicula gvp = new gestorValoracionPelicula();
			if (gvp.isVal(vp)) {
				boolean core;
				try {
					core = gvp.modificarValoracionPelicula(vp);
					if (core) {
						JOptionPane.showMessageDialog(new Frame(),
								"La pelicula se ha revalorado");
					} else {
						JOptionPane.showMessageDialog(new Frame(),
								"_NO_ se ha revalorado la pelicula");
					}

				} catch (ClassNotFoundException e1) {
					JOptionPane
							.showMessageDialog(null,
									"No existe la base de datos comprueba que existe el archivo sqlite");
					this.dispose();
				}

			} else {
				try {
					gvp.addValoracionPelicula(vp);
					if (gvp.isVal(vp)) {
						JOptionPane.showMessageDialog(new Frame(),
								"Se ha valorado la pelicula ");
					}
				} catch (excepAnadirDupli e1) {
				} catch (FaltanDatosEnLaBaseDeDatos e1) {
					JOptionPane.showMessageDialog(new Frame(), e1.getFalta());
				} catch (ClassNotFoundException e1) {
					JOptionPane
							.showMessageDialog(null,
									"No existe la base de datos comprueba que existe el archivo sqlite");
					this.dispose();
				}
			}
		}
	}

	@Override
	public void internalFrameIconified(InternalFrameEvent e) {
	}

	@Override
	public void internalFrameDeiconified(InternalFrameEvent e) {
	}

	@Override
	public void internalFrameActivated(InternalFrameEvent e) {
	}

	@Override
	public void internalFrameDeactivated(InternalFrameEvent e) {
	}
}
